﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Triples {
    public class CardSet : IEnumerable <ICard> {
	
		public const int SetSize = 3;
		private const int FirstCard = 0;
		private const int SecondCard = 1;
		private const int ThirdCard = 2;
		private readonly List<ICard> Cards;
		
		
		public CardSet () {
			Cards = new List<ICard> (SetSize);
		}
	
		public bool Add (ICard c) {

            if (Cards.Count < SetSize) {
                Cards.Add(c);
                return true;
            }

            return false;
		}
		
		
		public void Remove (ICard c) {
			if (Cards.Contains (c)) Cards.Remove (c);
		}
		
	
		public bool IsSet () {
			return Cards.Count == SetSize &&
				   IsSet (Cards [FirstCard], Cards [SecondCard], Cards [ThirdCard]);
		}
		

        public static bool IsSet(ICard c1, ICard c2, ICard c3) {

            return
                IsValidProperty(c1.Color, c2.Color, c3.Color) &&
                IsValidProperty(c1.Number, c2.Number, c3.Number) &&
                IsValidProperty(c1.Shade, c2.Shade, c3.Shade) &&
                IsValidProperty(c1.Shape, c2.Shape, c3.Shape);
        }
		

        private static bool IsValidProperty <T> (T b1, T b2, T b3) {
            return IsPropertyAllSame(b1, b2, b3) || IsPropertyAllDifferent(b1, b2, b3);
        }

		
        private static bool IsPropertyAllSame <T> (T b1, T b2, T b3) {
            return b1.Equals (b2) && b1.Equals(b3);
        }

		
        private static bool IsPropertyAllDifferent <T> (T b1, T b2, T b3) {
            return !b1.Equals (b2) && !b2.Equals (b3) && !b1.Equals (b3);
        }


        public IEnumerator<ICard> GetEnumerator() {
            return Cards.GetEnumerator();
        }


        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
            return Cards.GetEnumerator();
        }


        public override bool Equals(object obj) {
            return (obj is CardSet) && (obj as CardSet).Intersect(this, new CardComparer ()).Count() == Cards.Count;
        }


        public override int GetHashCode() {
            int hashCode = 0;
            CardComparer comparer = new CardComparer();

            hashCode += comparer.GetHashCode(Cards[FirstCard]);
            hashCode += comparer.GetHashCode(Cards[SecondCard]);
            hashCode += comparer.GetHashCode(Cards[ThirdCard]);
            return hashCode;
        }
    }
}
